﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using NUnit.Framework;
using Rhino.Mocks;
using Rhino.Mocks.Constraints;
using Source.Common;
using Source.ServerSide;
using Source.ServiceLayer;
using Is = Rhino.Mocks.Constraints.Is;

namespace Source.Tests.ServerSide
{
    [TestFixture]
    public class EmailMessageSenderTests : MockingTest
    {

        private IEmailMessageSender emailMessageSender;

        private IServerSideUserManager userManager;
        private IEmailTemplateProvider emailTemplateProvider;
        private IEmailClientProcessor emailClientProcessor;
        private IConfigurationProvider configurationProvider;

        private UserDto currentUser;

        protected override void AfterSetUp()
        {
            base.AfterSetUp();

            userManager = Mocks.DynamicMock<IServerSideUserManager>();
            emailTemplateProvider = Mocks.DynamicMock<IEmailTemplateProvider>();
            emailClientProcessor = Mocks.DynamicMock<IEmailClientProcessor>();
            configurationProvider = Mocks.DynamicMock<IConfigurationProvider>();

            emailMessageSender = new EmailMessageSender(userManager, emailTemplateProvider, emailClientProcessor, configurationProvider);

            currentUser = new UserDto { FirstName = "khgjh", LastName = "hjgjh" };
        }

        [Test]
        public void Send_CorrectTemplateLoadedAndPassedOn()
        {
            EmailMessageTypes emailMessageType = EmailMessageTypes.OrderRevoked;
            string templateContent = "blahblah";

            userManager.Stub(u => u.GetCurrentUserInfo()).Return(currentUser).Repeat.Any();
            emailTemplateProvider.Expect(e => e.LoadTemplate(emailMessageType.ToString())).Return(templateContent);
            emailClientProcessor.Expect(e => e.ProcessMail("", "", "", null, null)).Constraints(Is.Anything(), Is.Equal(templateContent), Is.Anything(), Is.Anything(), Is.Anything());

            Mocks.ReplayAll();
            emailMessageSender.Send(emailMessageType, new List<string>(), new List<string>(), new OrderEmailDetailViewDto());
            Mocks.VerifyAll();
        }

        [Test]
        public void Send_CorrectFromEmailUsed()
        {
            string expectedFromEmailAddress = "jhjkh";

            userManager.Stub(u => u.GetCurrentUserInfo()).Return(currentUser).Repeat.Any();
            emailTemplateProvider.Expect(e => e.LoadTemplate(null)).IgnoreArguments().Return("");

            configurationProvider.Expect(c => c.FromEmailAddress).Return(expectedFromEmailAddress);
            emailClientProcessor.Expect(e => e.ProcessMail("", "", "", null, null)).Constraints(Is.Anything(), Is.Anything(), Is.Equal(expectedFromEmailAddress), Is.Anything(), Is.Anything());

            Mocks.ReplayAll();
            emailMessageSender.Send(EmailMessageTypes.ApprovalRequired, new List<string>(), new List<string>(), new OrderEmailDetailViewDto());
            Mocks.VerifyAll();
        }

        [Test]
        public void Send_CorrectToAddressedPassed()
        {
            List<string> expectedToAddresses = new List<string> { "jklhh", "kjhkkjhk" };

            userManager.Stub(u => u.GetCurrentUserInfo()).Return(currentUser).Repeat.Any();
            emailTemplateProvider.Expect(e => e.LoadTemplate(null)).IgnoreArguments().Return("");

            emailClientProcessor.Expect(e => e.ProcessMail("", "", "", null, null)).Constraints(Is.Anything(), Is.Anything(), Is.Anything(), Is.Equal(expectedToAddresses), Is.Anything());

            Mocks.ReplayAll();
            int numberOfEmailsSent = emailMessageSender.Send(EmailMessageTypes.ApprovalRequired, expectedToAddresses, new List<string>(), new OrderEmailDetailViewDto());
            Mocks.VerifyAll();

            Assert.AreEqual(2, numberOfEmailsSent);
        }

        [Test]
        public void Send_CorrectCCAddressedPassed()
        {
            List<string> expectedCCAddresses = new List<string> { "jklhh" };

            userManager.Stub(u => u.GetCurrentUserInfo()).Return(currentUser).Repeat.Any();
            emailTemplateProvider.Expect(e => e.LoadTemplate(null)).IgnoreArguments().Return("");

            emailClientProcessor.Expect(e => e.ProcessMail("", "", "", null, null)).IgnoreArguments().Do(
                new Delegates.Action<string, string, string, IEnumerable<string>, IEnumerable<string>>(delegate(string subject, string body, string from, IEnumerable<string> to, IEnumerable<string> cc)
                {
                    Assert.IsNotNull(cc);
                    Assert.AreEqual(1, cc.Count());
                    Assert.AreEqual(expectedCCAddresses.ElementAt(0), cc.ElementAt(0));
                }));

            Mocks.ReplayAll();
            int numberOfEmailsSent = emailMessageSender.Send(EmailMessageTypes.ApprovalRequired, new List<string>(), expectedCCAddresses, new OrderEmailDetailViewDto());
            Mocks.VerifyAll();

            Assert.AreEqual(1, numberOfEmailsSent);
        }

        [Test]
        public void Send_DuplicateAddressesRemovedFromTO()
        {
            List<string> expectedToAddresses = new List<string> { "123456", "123456" };

            userManager.Stub(u => u.GetCurrentUserInfo()).Return(currentUser).Repeat.Any();
            emailTemplateProvider.Expect(e => e.LoadTemplate(null)).IgnoreArguments().Return("");

            emailClientProcessor.Expect(e => e.ProcessMail("", "", "", null, null)).IgnoreArguments().Do(
                new Delegates.Action<string, string, string, IEnumerable<string>, IEnumerable<string>>(delegate(string subject, string body, string from, IEnumerable<string> to, IEnumerable<string> cc)
                {
                    Assert.IsNotNull(to);
                    Assert.AreEqual(1, to.Count());
                    Assert.AreEqual(expectedToAddresses.ElementAt(0), to.ElementAt(0));
                }));

            Mocks.ReplayAll();
            int numberOfEmailsSent = emailMessageSender.Send(EmailMessageTypes.ApprovalRequired, expectedToAddresses, new List<string>(), new OrderEmailDetailViewDto());
            Mocks.VerifyAll();

            Assert.AreEqual(1, numberOfEmailsSent);
        }

        [Test]
        public void Send_DuplicateAddressesRemovedFromCC()
        {
            List<string> expectedCCAddresses = new List<string> { "78910", "78910" };

            userManager.Stub(u => u.GetCurrentUserInfo()).Return(currentUser).Repeat.Any();
            emailTemplateProvider.Expect(e => e.LoadTemplate(null)).IgnoreArguments().Return("");

            emailClientProcessor.Expect(e => e.ProcessMail("", "", "", null, null)).IgnoreArguments().Do(
                new Delegates.Action<string, string, string, IEnumerable<string>, IEnumerable<string>>(delegate(string subject, string body, string from, IEnumerable<string> to, IEnumerable<string> cc)
                {
                    Assert.IsNotNull(cc);
                    Assert.AreEqual(1, cc.Count());
                    Assert.AreEqual(expectedCCAddresses.ElementAt(0), cc.ElementAt(0));
                }));

            Mocks.ReplayAll();
            int numberOfEmailsSent = emailMessageSender.Send(EmailMessageTypes.ApprovalRequired, new List<string>(), expectedCCAddresses, new OrderEmailDetailViewDto());
            Mocks.VerifyAll();

            Assert.AreEqual(1, numberOfEmailsSent);
        }

        [Test]
        public void Send_RemoveAddressesInCCThatAreAlreadyInTO()
        {
            List<string> expectedTOAddresses = new List<string> { "78910" };
            List<string> expectedCCAddresses = new List<string> { "78910" };

            userManager.Stub(u => u.GetCurrentUserInfo()).Return(currentUser).Repeat.Any();
            emailTemplateProvider.Expect(e => e.LoadTemplate(null)).IgnoreArguments().Return("");

            emailClientProcessor.Expect(e => e.ProcessMail("", "", "", null, null)).IgnoreArguments().Do(
                new Delegates.Action<string, string, string, IEnumerable<string>, IEnumerable<string>>(delegate(string subject, string body, string from, IEnumerable<string> to, IEnumerable<string> cc)
                {
                    Assert.IsNotNull(to);
                    Assert.AreEqual(1, to.Count());

                    Assert.IsNotNull(cc);
                    Assert.AreEqual(0, cc.Count());
                }));

            Mocks.ReplayAll();
            int numberOfEmailsSent = emailMessageSender.Send(EmailMessageTypes.ApprovalRequired, expectedTOAddresses, expectedCCAddresses, new OrderEmailDetailViewDto());
            Mocks.VerifyAll();

            Assert.AreEqual(1, numberOfEmailsSent);
        }

        [Test]
        public void Send_TemplateParametersReplaced_OrderId()
        {
            OrderEmailDetailViewDto order = new OrderEmailDetailViewDto { OrderId = 45 };
            string template = "<%orderId%>";
            string expectedResult = "45";

            PerformTemplateParameterReplacementTest(template, expectedResult, order);
        }

        [Test]
        public void Send_TemplateParametersReplaced_CustomerName()
        {
            OrderEmailDetailViewDto order = new OrderEmailDetailViewDto { CustomerName = "some customer" };
            string template = "<%customerName%>";
            string expectedResult = order.CustomerName;

            PerformTemplateParameterReplacementTest(template, expectedResult, order);
        }

        [Test]
        public void Send_TemplateParametersReplaced_CustomerCountry()
        {
            OrderEmailDetailViewDto order = new OrderEmailDetailViewDto { CustomerCountry = "some country" };
            string template = "<%customerCountry%>";
            string expectedResult = order.CustomerCountry;

            PerformTemplateParameterReplacementTest(template, expectedResult, order);
        }

        [Test]
        public void Send_TemplateParametersReplaced_CustomerId()
        {
            OrderEmailDetailViewDto order = new OrderEmailDetailViewDto { CustomerId = "45" };
            string template = "<%customerId%>";
            string expectedResult = "45";

            PerformTemplateParameterReplacementTest(template, expectedResult, order);
        }

        [Test]
        public void Send_TemplateParametersReplaced_SellingUnit()
        {
            OrderEmailDetailViewDto order = new OrderEmailDetailViewDto { SellingEntityName = "some selling entity" };
            string template = "<%sellingUnit%>";
            string expectedResult = order.SellingEntityName;

            PerformTemplateParameterReplacementTest(template, expectedResult, order);
        }

        [Test]
        public void Send_TemplateParametersReplaced_CurrentDate()
        {
            DateTimeProvider.OverrideCurrentDateTime(new DateTime(2008, 5, 6, 10, 41, 0));

            OrderEmailDetailViewDto order = new OrderEmailDetailViewDto();
            string template = "<%currentDate%>";
            string expectedResult = "06/05/2008 10:41";

            PerformTemplateParameterReplacementTest(template, expectedResult, order);
        }

        [Test]
        public void Send_TemplateParametersReplaced_Creator()
        {
            OrderEmailDetailViewDto order = new OrderEmailDetailViewDto { CreatorName = "blabla" };
            string template = "<%creator%>";
            string expectedResult = order.CreatorName   ;

            PerformTemplateParameterReplacementTest(template, expectedResult, order);
        }

        [Test]
        public void Send_TemplateParametersReplaced_OrderStatus()
        {
            OrderEmailDetailViewDto order = new OrderEmailDetailViewDto { OrderStatus = "Approved" };
            string template = "<%orderStatus%>";
            string expectedResult = order.OrderStatus;

            PerformTemplateParameterReplacementTest(template, expectedResult, order);
        }

        [Test]
        public void Send_TemplateParametersReplaced_Requester()
        {
            OrderEmailDetailViewDto order = new OrderEmailDetailViewDto { RequesterName = "blabla" };
            string template = "<%requester%>";
            string expectedResult = order.RequesterName;

            PerformTemplateParameterReplacementTest(template, expectedResult, order);
        }

        [Test]
        public void Send_TemplateParametersReplaced_HyperlinkToOrder()
        {
            string orderLink = "http://localhost/Alu.Alliance.Workflow.Ola.Web/Orders/PopupOpener.aspx";
            OrderEmailDetailViewDto order = new OrderEmailDetailViewDto { OrderId = 45 };
            string template = "<%hyperlinkToOrder%>";
            string expectedResult = orderLink + "?" + QuerystringParameterKeys.OrderId + "=" + 45;

            configurationProvider.Expect(c => c.OpenOrderLink).Return(orderLink);

            PerformTemplateParameterReplacementTest(template, expectedResult, order);
        }

        [Test]
        public void Send_TemplateParametersReplaced_SubCategory()
        {
            OrderEmailDetailViewDto order = new OrderEmailDetailViewDto { SubCategoryName = "blabla" };
            string template = "<%subCategory%>";
            string expectedResult = order.SubCategoryName;

            PerformTemplateParameterReplacementTest(template, expectedResult, order);
        }

        [Test]
        public void Send_TemplateParametersReplaced_RsmType()
        {
            OrderEmailDetailViewDto order = new OrderEmailDetailViewDto { RsmTypeName = "blabla" };
            string template = "<%rsmType%>";
            string expectedResult = order.RsmTypeName;

            PerformTemplateParameterReplacementTest(template, expectedResult, order);
        }

        [Test]
        public void Send_TemplateParametersReplaced_CurrentUser_HasVisit()
        {
            currentUser.FirstName = "1st";
            currentUser.LastName = "2nd";

            string template = "<%currentUser%>";
            string expectedResult = currentUser.FirstName + " " + currentUser.LastName;

            userManager.Stub(u => u.HasVisit()).Return(true);
            userManager.Stub(u => u.GetCurrentUserInfo()).Return(currentUser).Repeat.Any();
            emailTemplateProvider.Expect(e => e.LoadTemplate(null)).IgnoreArguments().Return(template);

            emailClientProcessor.Expect(e => e.ProcessMail("", "", "", null, null)).Constraints(Is.Anything(), Is.Equal(expectedResult), Is.Anything(), Is.Anything(), Is.Anything());

            Mocks.ReplayAll();
            emailMessageSender.Send(EmailMessageTypes.Reminder, new List<string>(), new List<string>(), new OrderEmailDetailViewDto());
            Mocks.VerifyAll();
        }

        [Test]
        public void Send_TemplateParametersReplaced_CurrentUser_HasNoVisit()
        {
            currentUser.FirstName = "1st";
            currentUser.LastName = "2nd";

            string template = "<%currentUser%>";
            string expectedResult = "";

            userManager.Stub(u => u.HasVisit()).Return(false);
            emailTemplateProvider.Expect(e => e.LoadTemplate(null)).IgnoreArguments().Return(template);

            emailClientProcessor.Expect(e => e.ProcessMail("", "", "", null, null)).Constraints(Is.Anything(), Is.Equal(expectedResult), Is.Anything(), Is.Anything(), Is.Anything());

            Mocks.ReplayAll();
            emailMessageSender.Send(EmailMessageTypes.Reminder, new List<string>(), new List<string>(), new OrderEmailDetailViewDto());
            Mocks.VerifyAll();
        }

        private void PerformTemplateParameterReplacementTest(string template, string result, OrderEmailDetailViewDto order)
        {
            userManager.Stub(u => u.GetCurrentUserInfo()).Return(currentUser).Repeat.Any();
            emailTemplateProvider.Expect(e => e.LoadTemplate(null)).IgnoreArguments().Return(template);

            emailClientProcessor.Expect(e => e.ProcessMail("", "", "", null, null)).Constraints(Is.Anything(), Is.Equal(result), Is.Anything(), Is.Anything(), Is.Anything());

            Mocks.ReplayAll();
            emailMessageSender.Send(EmailMessageTypes.Reminder, new List<string>(), new List<string>(), order);
            Mocks.VerifyAll();
        }
    }
}
